package com.adnaan.backend.common.exception;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import com.adnaan.backend.common.model.Result;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.io.FileNotFoundException;

/**
 * author: adnaan
 * create: 2025-01-05 17:24
 * Description:
 */
@Slf4j
@RestController
@RestControllerAdvice
public class GlobalException implements ErrorController {

    @ExceptionHandler(value = NotLoginException.class)
    public Result<String> handle(NotLoginException e, HttpServletRequest request) {
        String tokenName = request.getHeader(StpUtil.getTokenName());
        if (StrUtil.isBlank(tokenName)) {
            return Result.error(401, "登陆失效，请重新登录！", request.getRequestURI());
        }
        log.error("未登录，鉴权异常：url:{}", request.getRequestURI(), e);
        return Result.error(401, e.getMessage(), request.getRequestURI());
    }

    @ExceptionHandler(value = NotPermissionException.class)
    public Result<String> handle(NotPermissionException e, HttpServletRequest request) {
        log.error("权限不够，鉴权异常：url:{}", request.getRequestURI(), e);
        return Result.error(403, e.getMessage(), request.getRequestURI());
    }

    @ExceptionHandler(value = NotRoleException.class)
    public Result<String> handle(NotRoleException e, HttpServletRequest request) {
        log.error("权限不够，鉴权异常：url:{}", request.getRequestURI(), e);
        return Result.error(403, e.getMessage(), request.getRequestURI());
    }

    /**
     * 业务异常
     */
    @ExceptionHandler(ServicesException.class)
    public Result<String> bizExceptionHandler(ServicesException e) {
        log.error("业务异常：原因:{}", e.getMessage());
        return Result.error(e.getCode(), e.getMessage());
    }

    @ExceptionHandler(FileNotFoundException.class)
    public Result<String> fileNotFoundException(FileNotFoundException e) {
        return Result.error(404, "文件不存在");
    }

    /**
     * 路径不匹配异常
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    public Result<String> handlerNoFoundException(Exception e) {
        return Result.error(404, "路径不存在，请检查路径是否正确");
    }

    /**
     * 拦截未知的运行时异常
     */
    @ExceptionHandler(RuntimeException.class)
    public Result<String> notFount(RuntimeException e) {
        return Result.error("运行时异常:" + e.getMessage());
    }

    /**
     * 基类异常
     */
    @ExceptionHandler(Exception.class)
    public Result<String> exceptionHandler(Exception e) {
        return Result.error(e.getMessage());
    }

    /**
     * 处理404错误
     */
    @RequestMapping("/error")
    public Result<String> handleError(HttpServletRequest request) {
        Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
        Object path = request.getAttribute(RequestDispatcher.ERROR_REQUEST_URI);
        Object message = request.getAttribute(RequestDispatcher.ERROR_MESSAGE);

        if (status != null) {
            int statusCode = Integer.parseInt(status.toString());
            String errorPath = path != null ? path.toString() : request.getRequestURI();
            String errorMessage = message != null ? message.toString() : "未知错误";

            if (statusCode == HttpStatus.NOT_FOUND.value()) {
                log.error("访问了不存在的路径: {}", errorPath);
                return Result.error(404, "请求的资源不存在: " + errorPath);
            } else {
                log.error("服务器错误: {} - {}", statusCode, errorMessage);
                return Result.error(statusCode, "服务器错误: " + errorMessage);
            }
        }

        return Result.error(500, "未知的服务器错误");
    }
}
